package org.takeback.chat.service;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.takeback.chat.entity.LoginLog;
import org.takeback.chat.entity.PubBank;
import org.takeback.chat.entity.PubExchangeLog;
import org.takeback.chat.entity.PubRecharge;
import org.takeback.chat.entity.PubRoomApply;
import org.takeback.chat.entity.PubShop;
import org.takeback.chat.entity.PubUser;
import org.takeback.chat.entity.PubWithdraw;
import org.takeback.chat.entity.ShareMoneyRecore;
import org.takeback.chat.entity.TransferLog;
import org.takeback.chat.lottery.listeners.GameException;
import org.takeback.chat.service.admin.SystemConfigService;
import org.takeback.chat.store.room.Room;
import org.takeback.service.BaseService;
import org.takeback.util.BeanUtils;
import org.takeback.util.encrypt.CryptoUtils;
import org.takeback.util.exception.CodedBaseRuntimeException;
import org.takeback.util.identity.UUIDGenerator;

import com.google.common.collect.ImmutableMap;

@Service
public class UserService extends BaseService {
	
	@Autowired
	protected LotteryService lotteryService;
	
	@Autowired
	protected ShareMoneyRecoreService shareMoneyRecoreService;
	
	@Transactional(rollbackFor = { Throwable.class })
	public PubUser updateUser(int uid, Map<String, Object> data) {
		PubUser pubUser = (PubUser) this.dao.get(PubUser.class, Integer.valueOf(uid));
		if (pubUser != null) {
			Map<String, Object> params = new HashMap();
			for (Map.Entry<String, Object> en : data.entrySet()) {
                if (en.getKey().equals("nickName") || en.getKey().equals("mobile") || en.getKey().equals("headImg") || en.getKey().equals("pwd") || en.getKey().equals("accessToken") || en.getKey().equals("tokenExpireTime")) {
                    params.put(en.getKey(), en.getValue());
				}
			}
			BeanUtils.copy(params, pubUser);
			this.dao.update(PubUser.class, pubUser);
		}
		return null;
	}

	@Transactional(rollbackFor = { Throwable.class })
	public void transfer(Integer uid, Integer account, Integer money) {
		if (!"1".equals(SystemConfigService.getValue("conf_transfer"))) {
			throw new CodedBaseRuntimeException("系统转账功能已关闭!");
		}
		PubUser target = (PubUser) this.dao.get(PubUser.class, account);
		if (target == null) {
			throw new CodedBaseRuntimeException("目标账号不存在!");
		}
		if (target.getId().equals(uid)) {
			throw new CodedBaseRuntimeException("不允许给自己转账!");
		}
		int effected = this.dao.executeUpdate("update PubUser set money=money -:money where money >:money and  id=:uid",
				ImmutableMap.of("money", Double.valueOf(money.intValue() + 0.0D), "uid", uid));
		if (effected == 0) {
			throw new CodedBaseRuntimeException("金额不足!");
		}
		this.dao.executeUpdate("update PubUser set money=money +:money where  id=:uid",
				ImmutableMap.of("money", Double.valueOf(money.intValue() + 0.0D), "uid", target.getId()));
		PubUser fromUser = (PubUser) this.dao.get(PubUser.class, uid);
		TransferLog tl = new TransferLog();
		tl.setFromUid(uid);
		tl.setFromNickName(fromUser.getUserId());
		tl.setToUid(target.getId());
		tl.setToNickName(target.getUserId());
        tl.setMoney(money + 0.0);
		tl.setTransferDate(new Date());
		this.dao.save(TransferLog.class, tl);
	}

	@Transactional(rollbackFor = { Throwable.class })
	public void prixyRecharge(Integer uid, Integer account, Integer money) {
		if (!"1".equals(SystemConfigService.getValue("conf_proxyRecharge"))) {
			throw new CodedBaseRuntimeException("功能已关闭!");
		}
		PubUser target = (PubUser) this.dao.get(PubUser.class, account);
		if (target == null) {
			throw new CodedBaseRuntimeException("目标账号不存在!");
		}
		if (target.getId().equals(uid)) {
			throw new CodedBaseRuntimeException("不允许给自己充值!");
		}
		if (!uid.equals(target.getParent())) {
			throw new CodedBaseRuntimeException("只能给直接下线上分!");
		}
		if (money.intValue() <= 0) {
			throw new CodedBaseRuntimeException("请输入大于0的金额!");
		}
		int effected = this.dao.executeUpdate("update PubUser set money=money -:money where money >:money and  id=:uid",
				ImmutableMap.of("money", Double.valueOf(money.intValue() + 0.0D), "uid", uid));
		if (effected == 0) {
			throw new CodedBaseRuntimeException("金额不足!");
		}
		this.dao.executeUpdate("update PubUser set money=money +:money where  id=:uid",
				ImmutableMap.of("money", Double.valueOf(money.intValue() + 0.0D), "uid", target.getId()));

		PubRecharge pubRecharge = new PubRecharge();
		pubRecharge.setStatus("1");
		pubRecharge.setDescpt("上分");
		pubRecharge.setFee(Double.valueOf(money.intValue() + 0.0D));
		pubRecharge.setGoodsname("上分");
		pubRecharge.setTradeno(UUIDGenerator.get());
		pubRecharge.setTradetime(new Date());
        pubRecharge.setGift(0.0);
		pubRecharge.setRechargeType("2");
		pubRecharge.setUid(account);
		pubRecharge.setUserIdText(target.getUserId());
		pubRecharge.setOperator(uid);
		this.dao.save(PubRecharge.class, pubRecharge);
	}

	@Transactional(rollbackFor = { Throwable.class })
	public void prixyUnRecharge(Integer uid, Integer account, Integer money) {
		if (!"1".equals(SystemConfigService.getValue("conf_proxyWithdraw"))) {
			throw new CodedBaseRuntimeException("功能已关闭!");
		}
		PubUser target = (PubUser) this.dao.get(PubUser.class, account);
		if (target == null) {
			throw new CodedBaseRuntimeException("目标账号不存在!");
		}
		if (target.getId().equals(uid)) {
			throw new CodedBaseRuntimeException("不允许给自己充值!");
		}
		if (!uid.equals(target.getParent())) {
			throw new CodedBaseRuntimeException("只能给直接下线下分!");
		}
		if (money.intValue() <= 0) {
			throw new CodedBaseRuntimeException("请输入大于0的金额!");
		}
		int effected = this.dao.executeUpdate(
				"update PubUser set money=money -:money where  id=:uid  and  money >:money",
				ImmutableMap.of("money", Double.valueOf(money.intValue() + 0.0D), "uid", target.getId()));
		if (effected == 0) {
			throw new CodedBaseRuntimeException("金额不足!");
		}
		this.dao.executeUpdate("update PubUser set money=money+:money where  id=:uid",
				ImmutableMap.of("money", Double.valueOf(money.intValue() + 0.0D), "uid", uid));

		PubRecharge pubRecharge = new PubRecharge();
		pubRecharge.setStatus("1");
		pubRecharge.setDescpt("下分");
		pubRecharge.setFee(Double.valueOf(money.intValue() + 0.0D));
		pubRecharge.setGoodsname("下分");
		pubRecharge.setTradeno(UUIDGenerator.get());
		pubRecharge.setTradetime(new Date());
        pubRecharge.setGift(0.0);
		pubRecharge.setRechargeType("3");
		pubRecharge.setUid(account);
		pubRecharge.setUserIdText(target.getUserId());
		pubRecharge.setOperator(uid);
		this.dao.save(PubRecharge.class, pubRecharge);
	}

	@Transactional(rollbackFor = { Throwable.class })
	public void exchange(Integer uid, Integer goodId, String name, String address, String mobile) {
		PubUser u = (PubUser) this.dao.get(PubUser.class, uid);
		PubShop s = (PubShop) this.dao.get(PubShop.class, goodId);
		if (s.getStorage().intValue() < 1) {
			throw new CodedBaseRuntimeException("库存商品!");
		}
		int effected = this.dao.executeUpdate(
				"update PubUser set money = coalesce(money,0) - :money where money>:money  and uid = :uid",
				ImmutableMap.of("money", s.getMoney(), "uid", uid));
		if (effected < 1) {
			throw new CodedBaseRuntimeException("账户金币不足!");
		}
		PubExchangeLog pel = new PubExchangeLog();
		pel.setStatus("0");
		pel.setAddress(address);
		pel.setExchangeTime(new Date());
		pel.setMobile(mobile);
		pel.setMoney(s.getMoney());
		pel.setName(name);
		pel.setShopId(goodId.toString());
		pel.setShopName(s.getName());
		pel.setUid(uid);
		this.dao.save(PubExchangeLog.class, pel);
	}

	@Transactional(rollbackFor = { Throwable.class })
	public void bindMobile(int uid, String mobile) {
		this.dao.executeUpdate("update PubUser set mobile=:mobile where id=:uid",
				ImmutableMap.of("mobile", mobile, "uid", Integer.valueOf(uid)));
	}

	@Transactional(rollbackFor = { Throwable.class })
	public void updatePwd(int uid, String pwd) {
		this.dao.executeUpdate("update PubUser set pwd=:pwd where id=:uid",
				ImmutableMap.of("pwd", pwd, "uid", Integer.valueOf(uid)));
	}

	@Transactional(rollbackFor = { Throwable.class })
	public void updateHeadImg(int uid, String headImg) {
		this.dao.executeUpdate("update PubUser set headImg=:headImg where id=:uid",
				ImmutableMap.of("headImg", headImg, "uid", Integer.valueOf(uid)));
	}

	@Transactional(readOnly = true)
	public PubUser login(String username, String password) {
		return get(username, password);
	}

	@Transactional
	public void setLoginInfo(String ip, Integer uid) {
		this.dao.executeUpdate("update PubUser set lastLoginDate=:loginDate,lastLoginIp = :lastLoginIp where id=:uid",
				ImmutableMap.of("loginDate", new Date(), "lastLoginIp", ip, "uid", uid));
	}

	@Transactional(readOnly = true)
	public PubUser get(String username, String password) {
		PubUser user = (PubUser) this.dao.getUnique(PubUser.class, "userId", username);
		if (user == null) {
			return null;
		}
		if (CryptoUtils.verify(user.getPwd(), password, StringUtils.reverse(user.getSalt()))) {
			return user;
		}
		return null;
	}

	@Transactional(readOnly = true)
	public PubUser get(int uid, String password) {
		PubUser user = (PubUser) this.dao.getUnique(PubUser.class, "id", Integer.valueOf(uid));
		if (user == null) {
			return null;
		}
		if (CryptoUtils.verify(user.getPwd(), password, StringUtils.reverse(user.getSalt()))) {
			return user;
		}
		return null;
	}

	@Transactional(readOnly = true)
	public double getBalance(int uid) {
		PubUser user = (PubUser) this.dao.getUnique(PubUser.class, "id", Integer.valueOf(uid));
		if (user == null) {
			return 0.0D;
		}
		return user.getMoney().doubleValue();
	}

	@Transactional(rollbackFor = { Throwable.class })
	public PubUser register(String username, String password, String mobile, String wx, String alipay, Integer parent,
			String ip) {
		PubUser user = (PubUser) this.dao.getUnique(PubUser.class, "userId", username);
		if (user != null) {
			throw new CodedBaseRuntimeException("用户名已存在!");
		}
		user = new PubUser();
		String salt = CryptoUtils.getSalt();
		user.setUserId(username);
		user.setNickName(username);
		user.setSalt(salt);
		user.setWx(wx);
		user.setUserType("1");
		user.setMobile(mobile);
		user.setLastLoginDate(new Date());
		user.setLastLoginIp(ip);
		user.setAlipay(alipay);
		user.setPwd(CryptoUtils.getHash(password, StringUtils.reverse(salt)));
		user.setMoneyCode(user.getPwd());
		user.setMoney(Double.valueOf(0.0D));
		Object conf = SystemConfigService.getValue("conf_init_money");
		if (conf != null) {
			try {
				user.setMoney(Double.valueOf(conf.toString()));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		user.setRegistDate(new Date());
		user.setUserType("1");
		user.setRegistIp(ip);
		if (parent != null) {
			PubUser p = (PubUser) this.dao.get(PubUser.class, parent);
			if (p != null) {
				user.setParent(parent);
			}
		}
		this.dao.save(PubUser.class, user);

		LoginLog l = new LoginLog();
		l.setLoginTime(new Date());
		l.setIp(ip);
		l.setUserId(user.getId());
		l.setUserName(user.getUserId());

		this.dao.save(LoginLog.class, l);
		return user;
	}

	@Transactional(readOnly = true)
	public PubUser getByWxOpenId(String openId) {
		return (PubUser) this.dao.getUnique(PubUser.class, "wxOpenId", openId);
	}

	@Transactional(rollbackFor = { Throwable.class })
	public void roomApply(String name, String mobile, int uid) {
		PubRoomApply r = new PubRoomApply();
		r.setName(name);
		r.setCreateTime(new Date());
		r.setMobile(mobile);
		r.setUid(Integer.valueOf(uid));
		PubUser user = (PubUser) this.dao.get(PubUser.class, Integer.valueOf(uid));
		r.setUserIdText(user.getUserId());
		this.dao.save(PubRoomApply.class, r);
	}

	@Transactional(rollbackFor = { Throwable.class })
	public void proxyApply(Integer uid, Map<String, Object> conf) {
		PubUser u = (PubUser) this.dao.get(PubUser.class, uid);
		if ("2".equals(u.getUserType())) {
			throw new CodedBaseRuntimeException("你已经是代理,无需申请!");
		}
		Double limit = Double.valueOf(conf.get("money").toString());
		int effected = this.dao.executeUpdate(
				"update PubUser set money=coalesce(money,0)-:money where money>=:money and  id =:uid ",
				ImmutableMap.of("money", limit, "uid", uid));
		if (effected == 0) {
			throw new CodedBaseRuntimeException("账户金币不足,申请失败!");
		}
		this.dao.executeUpdate("update PubUser set userType = '2' where id =:uid ", ImmutableMap.of("uid", uid));
	}

	@Transactional(rollbackFor = { Throwable.class })
	public void withdraw(Map<String, Object> data, int uid) {
		double money = Double.valueOf(data.get("money").toString()).doubleValue();
		if (money < 50.0D) {
			throw new CodedBaseRuntimeException("提现金额必须大于50");
		}
		String bankName = data.get("bankName").toString();
		String account = data.get("account").toString();
		String branch = data.get("branch").toString();
		String ownerName = data.get("ownerName").toString();
		String mobile = data.get("mobile").toString();

		String hql = "update PubUser set money = money - :money where id=:id and money > :money";
		int effect = this.dao.executeUpdate(hql,
				ImmutableMap.of("money", Double.valueOf(money), "id", Integer.valueOf(uid)));
		if (effect == 0) {
			throw new CodedBaseRuntimeException("金额不足");
		}
		PubWithdraw pw = new PubWithdraw();
		pw.setAccount(account);
		pw.setBankName(bankName);
		pw.setBranch(branch);
		pw.setFee(Double.valueOf(money));
		pw.setMobile(mobile);
		pw.setOwnerName(ownerName);
		pw.setUid(Integer.valueOf(uid));
		PubUser user = (PubUser) this.dao.get(PubUser.class, Integer.valueOf(uid));
		pw.setUserIdText(user.getUserId());
		pw.setStatus("1");
		pw.setTradetime(new Date());
		this.dao.save(PubWithdraw.class, pw);

		String hql2 = "from PubBank where userId=:userId and account =:account";
		List<PubBank> bankList = this.dao.findByHql(hql2,
				ImmutableMap.of("userId", Integer.valueOf(uid), "account", account));
		PubBank pb;
		if (bankList.size() == 0) {
			pb = new PubBank();
			pb.setCreateTime(new Date());
			pb.setUserId(Integer.valueOf(uid));
		} else {
			pb = (PubBank) bankList.get(0);
		}
		pb.setMobile(mobile);
		pb.setUserIdText(user.getUserId());
		pb.setBranch(branch);
		pb.setAccount(account);
		pb.setBankName(bankName);
		pb.setName(ownerName);
		this.dao.saveOrUpdate(PubBank.class, pb);
	}
	
	/**
	 * 佣金分享
	 * 如果是龙虎合 money是用户押注的总金额
	 * 如果是牛牛money
	 * 如果是扫雷money  TODO hbNumber牛牛红包个数
	 * @param userId
	 * @param money
	 */
	@Transactional(rollbackFor = { Throwable.class })
	public Double shareYongjin(Integer userId, Double money, Room room) {
		
		Double shareMoney = 0.00;//剩余金额
		//当前用户
		try {
			PubUser user = (PubUser) this.dao.get(PubUser.class, userId);
			//如果没有邀请人 直接返回
			if(user.getParent() == null) return money;
			//当前用户上一级用户
			PubUser user2 = (PubUser) this.dao.get(PubUser.class, user.getParent());
			//当前用户上一级用户的上一级用户
			PubUser user3 = null;
			
			PubUser user4 = null;
			if(user2 != null && user2.getParent() != null) {
				user3 = (PubUser) this.dao.get(PubUser.class, user2.getParent());
			}
			if(user3 != null && user3.getParent() != null){
				user4 = (PubUser) this.dao.get(PubUser.class, user3.getParent());
			}
			//龙虎合
			if(SystemConfigService.getValue("lhh_yong_jin0") == null || SystemConfigService.getValue("lhh_yong_jin1") == null || SystemConfigService.getValue("lhh_yong_jin2") == null) {
				return money;
			}
			//一级
			Double lhhYongjin0 = Double.valueOf(SystemConfigService.getValue("lhh_yong_jin0"));
			//一级2%
			Double lhhYongjin1 = Double.valueOf(SystemConfigService.getValue("lhh_yong_jin1"));
			//二级
			Double lhhYongjin2 = Double.valueOf(SystemConfigService.getValue("lhh_yong_jin2"));
			//到这个地方  肯定有上级
			Double share1ToleMoney = m2(money * lhhYongjin0);
			Double share2ToleMoney = m2(money * lhhYongjin1);
			Double share3ToleMoney = m2(money * lhhYongjin2);
			System.out.println("分享出去的佣金分别是：" + share1ToleMoney +"<<>>" + share2ToleMoney +"<<>>" +share3ToleMoney);
			//上级
			int r1 = lotteryService.moneyUp(user2.getId(), share1ToleMoney);//上级
			int w1 = lotteryService.userUaterUp(user2.getId(), share1ToleMoney);
			if(r1 > 0) {
				ShareMoneyRecore smr = new ShareMoneyRecore();
				smr.setMoney(share2ToleMoney);
				smr.setUserId(user2.getId());
				smr.setUserName(user.getNickName());
				shareMoney =  share1ToleMoney;
			}
			//上上级
			if(user3 != null) {
				int r2 = lotteryService.moneyUp(user3.getId(), share2ToleMoney);//上上级
				int w2 = lotteryService.userUaterUp(user3.getId(), share2ToleMoney);
				if(r2 > 0) {
					ShareMoneyRecore smr = new ShareMoneyRecore();
					smr.setMoney(share2ToleMoney);
					smr.setUserId(user2.getId());
					smr.setUserName(user.getNickName());
//					smr.set
					shareMoneyRecoreService.save(ShareMoneyRecore.class, smr);
					shareMoney += share2ToleMoney;
				}
			}
			//上上级
			if(user4 != null) {
				int r2 = lotteryService.moneyUp(user4.getId(), share3ToleMoney);//上上级
				int w3 = lotteryService.userUaterUp(user4.getId(), share3ToleMoney);
				if(r2 > 0) {
					ShareMoneyRecore smr = new ShareMoneyRecore();
					smr.setMoney(share2ToleMoney);
					smr.setUserId(user2.getId());
					smr.setUserName(user.getNickName());
					shareMoney += share3ToleMoney;
				}
			}
			if(room.getType().equals("G022")){
				int res = lotteryService.moneyDown(userId, shareMoney);
				if(res < 1) {
					return 0.00;
				}
			}
		} catch (Exception e) {
			System.out.println("分佣金失败" + e.getMessage());
		}
		return money - shareMoney;
	}
	
	/** 
     * DecimalFormat转换最简便  保留两位小数
	 * @return 
     */  
    public static Double m2(double f) {  
        DecimalFormat df = new DecimalFormat(".##");  
        return Double.parseDouble(df.format(f));  
    }
    
    public static void main(String[] args) {
    	System.out.println(new Double(1));
	}
    
    
}
